package cn.demoncat.util.lang;

import cn.demoncat.util.exception.ParamRuntimeException;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.text.DecimalFormat;

/**
 * 
 * 
 * 描述：数值处理工具
 *
 * @author yxl
 *
 * @version 2.0
 *
 * @since 2016-12-9
 */
public final class NumberUtil {


	/**
	 * 格式
	 */
	public interface Format{
		/**
		 * 0
		 */
		String INT = "0";
		/**
		 * 0.##
		 */
		String FLOAT = "0.##";
		/**
		 * 0.00
		 */
		String DOUBLE = "0.00";
		/**
		 * #,##0.##
		 */
		String PRICE_FLOAT = "#,##0.##";
		/**
		 * #,##0.00
		 */
		String PRICE = "#,##0.00";
		/**
		 * 重量 0.###
		 */
		String WEIGHT_FLOAT = "0.###";
		/**
		 * 重量 0.000
		 */
		String WEIGHT = "0.000";
		/**
		 * 百分比 0% ，格式化时会*100
		 */
		String PERCENT = "0%";
		/**
		 * 百分比0.##%，格式化时会*100
		 */
		String PERCENT_FLOAT = "0.##%";
		/**
		 * 百分比0.00%，格式化时会*100
		 */
		String PERCENT_DOUBLE = "0.00%";
	}

	/**
	 * 长度
	 *
	 * @param num
	 * @return
	 */
	public static int length(Number num){
		return num == null ? 0 : num.toString().length();
	}

	/**
	 * 判断数值为null或为0
	 * 
	 * @param num
	 * @return
	 */
	public static boolean isBlank(Number num){
		return num == null || num.doubleValue() == 0;
	}
	
	/**
	 * 判断数值为null或小于0
	 * 
	 * @param num
	 * @return
	 */
	public static boolean isNegative(Number num){
		return num == null || num.doubleValue() < 0;
	}
	
	/**
	 * 判断数值非空且大于0
	 * 
	 * @param num
	 * @return
	 */
	public static boolean isPositive(Number num){
		return num != null && num.doubleValue() > 0;
	}
	
	/**
	 * 功能描述：格式化数值
	 *
	 * @param src 源数值如果为空，按0计算
	 * @param format
	 * @return 格式化字符串
	 * 
	 * @author yxl
	 *
	 * @since 2016-12-10
	 *
	 * @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
	 */
	public static String format(Number src, String format){
		if (src == null) {
			src = 0;
		}
		return new DecimalFormat(format).format(src);
	}
 
	/**
	 * 功能描述：格式化数值
	 *
	 * @param src 源数值如果为空，按0计算
	 * @param format
	 * @return 格式化字符串
	 * 
	 * @author yxl
	 *
	 * @since 2016-12-10
	 *
	 * @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
	 */
	public static String format(String src, String format){
		return format(DoubleUtil.valueOf(src),format);
	}
	
	/**
	 * 功能描述：格式化数值
	 *
	 * @param src 源数值如果为空，按0计算
	 * 
	 * @return 格式化字符串：#.##
	 * 
	 * @author yxl
	 *
	 * @since 2016-12-10
	 *
	 * @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
	 */
	public static String format(Number src){
		return format(src, Format.FLOAT);
	}
 
	/**
	 * 功能描述：格式化数值
	 *
	 * @param src 源数值如果为空，按0计算
	 * 
	 * @return 格式化字符串：#.##
	 * 
	 * @author yxl
	 *
	 * @since 2016-12-10
	 *
	 * @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
	 */
	public static String format(String src){
		return format(src, Format.FLOAT);
	}
	
	/**
	 * 转换数字为字符串
	 * 
	 * 1、去掉末尾的0
	 * 2、解决科学计数法问题
	 * 
	 * @param num
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2018年7月19日
	 */
	public static String toString(String num) {
		return DecimalUtil.toString(DecimalUtil.valueOf(num));
	}
	
	/**
	 * 转换数据为字符串
	 * 
	 * 1、去掉末尾的0
	 * 2、解决科学计数法问题
	 * 3、如果为.0，舍去小数位
	 * 
	 * @param num
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2018年7月19日
	 */
	public static String toString(double num) {
		if (DoubleUtil.isInteger(num)) {
			// 整数
			return toString(DoubleUtil.toLong(num));
		}
		return DecimalUtil.toString(BigDecimal.valueOf(num));
	}
 
	/**
	 * 转换数据为字符串
	 * 
	 * 1、解决科学计数法问题
	 * 
	 * @param num
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2018年7月19日
	 */
	public static String toString(long num) {
		return BigDecimal.valueOf(num).toPlainString();
	}
	
	/**
	 * 转换数据为字符串
	 * 
	 * 1、解决科学计数法问题
	 * 
	 * @param num
	 * @param scale	小数位
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2018年7月19日
	 */
	public static String toString(String num, int scale) {
		return DecimalUtil.valueOfZero(num).setScale(scale, BigDecimal.ROUND_HALF_UP).toPlainString();
	}
	
	/**
	 * 转换数据为字符串
	 * 
	 * 1、解决科学计数法问题
	 * 
	 * @param num
	 * @param scale	小数位
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2018年7月19日
	 */
	public static String toString(double num, int scale) {
		return BigDecimal.valueOf(num).setScale(scale, BigDecimal.ROUND_HALF_UP).toPlainString();
	}
	
	/**
	 * 转换数据为字符串
	 * 
	 * 1、解决科学计数法问题
	 * 
	 * @param num
	 * @param scale	小数位
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2018年7月19日
	 */
	public static String toString(long num, int scale) {
		return new BigDecimal(num).setScale(scale, BigDecimal.ROUND_HALF_UP).toPlainString();
	}

	/**
	 * 数量校验
	 *
	 * @param num
	 * @param desc		目标：如"商品数量"、"订单数量"，默认"数量"
	 * @return 必须大于0
	 *
	 * @author 延晓磊
	 * @since 2021年03月05日
	 */
	public static <N extends Number>N check(N num, String desc){
		if(StringUtils.isBlank(desc)){
			desc = "数量";
		}
		if (num == null) {
			throw new ParamRuntimeException(desc + "不能为空");
		}
		if (num.doubleValue() <= 0) {
			throw new ParamRuntimeException(desc + "必须大于0");
		}
		return num;
	}
}


